// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of DOM3XPath
//
// DOM3XPath is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// DOM3XPath is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with DOM3ImplReg. If not, see <http://www.gnu.org/licenses/>.
//	
//
//   $Id$

// DOM3XPath.cpp : Implementation of DLL Exports.


// Note: Proxy/Stub Information
//      To build a separate proxy/stub DLL, 
//      run nmake -f DOM3XPathps.mk in the project directory.

#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include <DOM3XPath.h>
#include <DOM3XPath_i.c>
#include "XPathExpression.h"
#include "XPathResult.h"
#include "XPathNSResolver.h"
#include "XPathEvaluator.h"
#include "XPathHelper.h"

CComModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_XPathExpression, CXPathExpression)
OBJECT_ENTRY(CLSID_XPathResult, CXPathResult)
OBJECT_ENTRY(CLSID_XPathNSResolver, CXPathNSResolver)
OBJECT_ENTRY(CLSID_XPathEvaluator, CXPathEvaluator)
OBJECT_ENTRY(CLSID_XPathHelper, CXPathHelper)
END_OBJECT_MAP()


/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _Module.Init(ObjectMap, hInstance, &LIBID_DOM3XPATHLib);
        DisableThreadLibraryCalls(hInstance);
	}
    else if (dwReason == DLL_PROCESS_DETACH)
	{
		g_sHelperURI.Empty();
	//	g_pXSL->Release(); //won't let me release here.
		_Module.Term();
	}
    return TRUE;    // ok
}

/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE

STDAPI DllCanUnloadNow(void)
{
    return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
    return _Module.GetClassObject(rclsid, riid, ppv);
}

/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)
{
    // registers object, typelib and all interfaces in typelib
    return _Module.RegisterServer(TRUE);
}

/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
    return _Module.UnregisterServer(TRUE);
}
bool g_bInitDone = false;

HRESULT InitGlobals()
{
	HRESULT hr = S_OK;
	if(!g_bInitDone)
	{
		g_sHelperURI = "http://www.x-port.net/DOM3XPath";

		hr = CoInitialize(NULL);
		if(SUCCEEDED(hr))
		{
			hr =CoCreateInstance(
				CLSID_DOMDocument60,
				NULL,
				CLSCTX_SERVER,
				IID_IXMLDOMDocument2,
				(void**) &g_pXSL);

			hr =CoCreateInstance(
				CLSID_FreeThreadedDOMDocument60,
				NULL,
				CLSCTX_SERVER,
				IID_IXMLDOMDocument3,
				(void**) &g_FTXMLDOM);
			if(SUCCEEDED(hr))
			{
				/*
				* Initialise the regular expression parser that will be used when checking
				* for non-namespace prefixed functions.
				*
				* We're looking for either (a) Core XPath functions and namespace qualified
				* functions or (b) non-namespace qualified functions. The first we pass through
				* unmodified, whilst the second we map, and then prefix with the default prefix.
				*
				* Note that the two groups have to be in the order they are in the Parse() call,
				* otherwise the regular expression will always match the non-namespace qualified
				* group.
				*/

				const CAtlRegExp<CAtlRECharTraitsW>::RECHAR* szParse =
				//ignore quoted strings.
				L"{'.*?'}|"
				L"("
					L"("
					//GROUP 1 - the first group is anything that we want to just pass through unmodified
						L"{"
						//XPath Node-test expressions that look like functions
							/* http://www.www.org/TR/xpath#NT-NodeType */
							L"(comment)|(text)|(processing-instruction)|(node)"
						
						//XPath functions.
							/* http://www.w3.org/TR/xpath#section-Node-Set-Functions */
							L"|(last)|(position)|(count)|(id)|(local-name)|(namespace-uri)|(name)"
							/* http://www.w3.org/TR/xpath#section-String-Functions */
							L"|(string)|(concat)|(starts-with)|(contains)|(substring-before)|(substring-after)|(substring)|(string-length)|(normalize-space)|(translate)"
							/* http://www.w3.org/TR/xpath#section-Boolean-Functions */
							L"|(boolean)|(not)|(true)|(false)|(lang)"
							/* http://www.w3.org/TR/xpath#section-Number-Functions */
							L"|(number)|(sum)|(floor)|(ceiling)|(round)"

						L"}"
						L"|"
						//Group 2 - Extension functions - i.e., already namespace qualified
						L"{"
							/* http://www.w3.org/TR/REC-xml-names/#ns-qualnames */
							L"("
								/* http://www.w3.org/TR/REC-xml-names/#NT-NCName */
								L"\\a|_"
									/* http://www.w3.org/TR/REC-xml-names/#NT-NCNameChar */
									L"(\\a|[_\\-\\.])*"
								L":"
								/* http://www.w3.org/TR/REC-xml-names/#NT-NCName */
								L"\\a|_"
									/* http://www.w3.org/TR/REC-xml-names/#NT-NCNameChar */
									L"(\\a|[_\\-\\.])*"
							L")"
						L"}"
						//Group 3 - XSLT functions
						L"|"
						L"{"
												
							/* http://www.w3.org/TR/xslt#document */
							L"(document)"
							/* http://www.w3.org/TR/xslt#key */
							L"|(key)"
							/* http://www.w3.org/TR/xslt#format-number */
							L"|(format-number)"
							/* http://www.w3.org/TR/xslt#misc-func */
							L"|(current)|(generate-id)|(system-property)"
						L"}"
					//GROUP 4 - the fourth group is 'anything else', i.e., functions that are not
					//			qualified, and so need to use the default function library
						L"|"
						L"{"
							/* http://www.w3.org/TR/REC-xml-names/#NT-NCName */
							L"\\a|_"
								/* http://www.w3.org/TR/REC-xml-names/#NT-NCNameChar */
								L"(\\a|[_\\-\\.])*"
						L"}"


					L")"
					/* any of the preceding, followed by an opening parenthesis, means a function */
					L"\\("
					L")";
				REParseError status = g_re.Parse(szParse);

				if(REPARSE_ERROR_OK == status)
				{
					//	as long as the global xsl document has been created, 
					//	and there are no errors in the resource file, There is
					//	no excuse for failure in this branch.
					CComBSTR sXSL;
					sXSL.LoadString(IDS_XSL);
					VARIANT_BOOL bSuccess;
					hr = g_pXSL->loadXML(sXSL,&bSuccess);
					sXSL.Empty();
					if(SUCCEEDED(hr))
					{
						hr = g_pXSL->setProperty(CComBSTR("SelectionNamespaces"),CComVariant("xmlns:xsl=\'http://www.w3.org/1999/XSL/Transform\'"));
						if(SUCCEEDED(hr))
						{
							hr = g_pXSL->setProperty(CComBSTR("NewParser"),CComVariant(true));
						}
					}
				}
				else
				{
					hr = E_FAIL;
				}
			}
		}

		g_bInitDone = true;
	}

	return hr;
}

#include "XPathEvaluator.h"
#include "XPathHelper.h"
